import re
from typing import List, Dict, Set, Tuple
from dataclasses import dataclass
from static_configuration import picture_style, scene_description


@dataclass
class ConsistencyIssue:
    """一致性问题"""
    type: str  # 问题类型
    description: str  # 问题描述
    segments: List[int]  # 涉及的段落
    severity: str  # 严重程度: high, medium, low


class ConsistencyValidator:
    """一致性验证器"""
    
    def __init__(self):
        self.character_keywords = [
            '长发', '短发', '黑发', '金发', '棕发',
            '蓝眼', '棕眼', '绿眼',
            '高个', '矮个', '瘦弱', '健壮',
            '年轻', '中年', '老者'
        ]
        self.style_keywords = [
            '{picture_style}', '动漫', '写实', '油画', '水彩',
            '像素', '3D', '手绘', '电影级'.format(picture_style=picture_style)
        ]
        self.environment_keywords = [
            '现代', '古代', '未来', '科幻', '魔幻',
            '废土', '末世', '都市', '乡村'
        ]
    
    def validate_prompts(self, prompts: List[str]) -> List[ConsistencyIssue]:
        """验证提示词列表的一致性"""
        issues = []
        
        # 检查艺术风格一致性
        style_issues = self._check_style_consistency(prompts)
        issues.extend(style_issues)
        
        # 检查角色描述一致性
        character_issues = self._check_character_consistency(prompts)
        issues.extend(character_issues)
        
        # 检查环境设定一致性
        environment_issues = self._check_environment_consistency(prompts)
        issues.extend(environment_issues)
        
        # 检查色调一致性
        color_issues = self._check_color_consistency(prompts)
        issues.extend(color_issues)
        
        return issues
    
    def _check_style_consistency(self, prompts: List[str]) -> List[ConsistencyIssue]:
        """检查艺术风格一致性"""
        issues = []
        styles_found = {}
        
        for i, prompt in enumerate(prompts):
            for style in self.style_keywords:
                if style in prompt:
                    if style not in styles_found:
                        styles_found[style] = []
                    styles_found[style].append(i)
        
        # 如果发现多种风格
        if len(styles_found) > 1:
            issues.append(ConsistencyIssue(
                type="style_inconsistency",
                description=f"发现多种艺术风格: {', '.join(styles_found.keys())}",
                segments=list(range(len(prompts))),
                severity="high"
            ))
        
        return issues
    
    def _check_character_consistency(self, prompts: List[str]) -> List[ConsistencyIssue]:
        """检查角色描述一致性"""
        issues = []
        
        # 提取角色名称
        character_names = self._extract_character_names(prompts)
        
        for char_name in character_names:
            char_descriptions = {}
            
            for i, prompt in enumerate(prompts):
                if char_name in prompt:
                    # 提取该角色在此段落中的描述
                    char_desc = self._extract_character_description(prompt, char_name)
                    if char_desc:
                        char_descriptions[i] = char_desc
            
            # 检查描述是否一致
            if len(char_descriptions) > 1:
                inconsistencies = self._find_description_inconsistencies(char_descriptions)
                if inconsistencies:
                    issues.append(ConsistencyIssue(
                        type="character_inconsistency",
                        description=f"角色 {char_name} 的描述不一致: {inconsistencies}",
                        segments=list(char_descriptions.keys()),
                        severity="medium"
                    ))
        
        return issues
    
    def _check_environment_consistency(self, prompts: List[str]) -> List[ConsistencyIssue]:
        """检查环境设定一致性"""
        issues = []
        environments_found = {}
        
        for i, prompt in enumerate(prompts):
            for env in self.environment_keywords:
                if env in prompt:
                    if env not in environments_found:
                        environments_found[env] = []
                    environments_found[env].append(i)
        
        # 检查是否有冲突的环境设定
        conflicting_envs = [
            (['现代', '都市'], ['古代', '魔幻']),
            (['科幻', '未来'], ['古代']),
            (['废土', '末世'], ['现代', '都市'])
        ]
        
        for group1, group2 in conflicting_envs:
            found_group1 = any(env in environments_found for env in group1)
            found_group2 = any(env in environments_found for env in group2)
            
            if found_group1 and found_group2:
                issues.append(ConsistencyIssue(
                    type="environment_conflict",
                    description=f"环境设定冲突: {group1} vs {group2}",
                    segments=list(range(len(prompts))),
                    severity="high"
                ))
        
        return issues
    
    def _check_color_consistency(self, prompts: List[str]) -> List[ConsistencyIssue]:
        """检查色调一致性"""
        issues = []
        color_tones = {
            'warm': ['暖色调', '温暖', '金色', '橙色', '红色'],
            'cool': ['冷色调', '蓝色', '绿色', '青色'],
            'dark': ['暗色调', '黑暗', '昏暗', '阴暗'],
            'bright': ['明亮', '鲜艳', '高饱和度']
        }
        
        tone_counts = {tone: 0 for tone in color_tones.keys()}
        
        for prompt in prompts:
            for tone, keywords in color_tones.items():
                if any(keyword in prompt for keyword in keywords):
                    tone_counts[tone] += 1
        
        # 检查是否有冲突的色调
        if tone_counts['warm'] > 0 and tone_counts['cool'] > 0:
            issues.append(ConsistencyIssue(
                type="color_tone_conflict",
                description="色调冲突：同时出现暖色调和冷色调",
                segments=list(range(len(prompts))),
                severity="medium"
            ))
        
        if tone_counts['dark'] > 0 and tone_counts['bright'] > 0:
            issues.append(ConsistencyIssue(
                type="brightness_conflict", 
                description="亮度冲突：同时出现暗色调和明亮色调",
                segments=list(range(len(prompts))),
                severity="low"
            ))
        
        return issues
    
    def _extract_character_names(self, prompts: List[str]) -> Set[str]:
        """提取角色名称"""
        names = set()
        
        # 中文名字模式
        chinese_name_pattern = r'[\u4e00-\u9fff]{2,3}'
        # 英文名字模式  
        english_name_pattern = r'[A-Z][a-z]+'
        
        for prompt in prompts:
            chinese_names = re.findall(chinese_name_pattern, prompt)
            english_names = re.findall(english_name_pattern, prompt)
            
            # 过滤常见词汇，只保留可能的人名
            for name in chinese_names + english_names:
                if len(name) >= 2 and name not in ['吉卜力', '电影', '画质']:
                    names.add(name)
        
        return names
    
    def _extract_character_description(self, prompt: str, char_name: str) -> Dict[str, str]:
        """提取角色描述"""
        description = {}
        
        # 查找角色相关的形容词
        for keyword in self.character_keywords:
            if keyword in prompt and char_name in prompt:
                category = self._categorize_keyword(keyword)
                if category not in description:
                    description[category] = []
                description[category].append(keyword)
        
        return description
    
    def _categorize_keyword(self, keyword: str) -> str:
        """将关键词分类"""
        hair_keywords = ['长发', '短发', '黑发', '金发', '棕发']
        eye_keywords = ['蓝眼', '棕眼', '绿眼']
        body_keywords = ['高个', '矮个', '瘦弱', '健壮']
        age_keywords = ['年轻', '中年', '老者']
        
        if keyword in hair_keywords:
            return 'hair'
        elif keyword in eye_keywords:
            return 'eyes'
        elif keyword in body_keywords:
            return 'body'
        elif keyword in age_keywords:
            return 'age'
        else:
            return 'other'
    
    def _find_description_inconsistencies(self, descriptions: Dict[int, Dict[str, str]]) -> str:
        """查找描述不一致的地方"""
        inconsistencies = []
        
        # 比较每个类别的描述
        categories = set()
        for desc in descriptions.values():
            categories.update(desc.keys())
        
        for category in categories:
            values = []
            for desc in descriptions.values():
                if category in desc:
                    values.extend(desc[category])
            
            # 如果同一类别有不同的值
            unique_values = set(values)
            if len(unique_values) > 1:
                inconsistencies.append(f"{category}: {', '.join(unique_values)}")
        
        return '; '.join(inconsistencies)
    
    def generate_consistency_report(self, issues: List[ConsistencyIssue]) -> str:
        """生成一致性检查报告"""
        if not issues:
            return "✅ 一致性检查通过，未发现问题。"
        
        report = f"⚠️ 发现 {len(issues)} 个一致性问题：\n\n"
        
        # 按严重程度分组
        high_issues = [issue for issue in issues if issue.severity == "high"]
        medium_issues = [issue for issue in issues if issue.severity == "medium"]
        low_issues = [issue for issue in issues if issue.severity == "low"]
        
        if high_issues:
            report += "🔴 高严重度问题：\n"
            for issue in high_issues:
                report += f"- {issue.description} (段落: {', '.join(map(str, issue.segments))})\n"
            report += "\n"
        
        if medium_issues:
            report += "🟡 中等严重度问题：\n"
            for issue in medium_issues:
                report += f"- {issue.description} (段落: {', '.join(map(str, issue.segments))})\n"
            report += "\n"
        
        if low_issues:
            report += "🟢 低严重度问题：\n"
            for issue in low_issues:
                report += f"- {issue.description} (段落: {', '.join(map(str, issue.segments))})\n"
            report += "\n"
        
        return report